diff options
author | Kirill Podoprigora <kirill.bast9@mail.ru> | 2024-02-23 17:31:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-23 17:31:57 (GMT) |
commit | e4561e050148f6dc347e8c7ba30c8125b5fc0e45 (patch) | |
tree | 4df655662a8fc71c8e8497b6f3517d72ea22d4b4 /Tools/cases_generator | |
parent | 59057ce55a443f35bfd685c688071aebad7b3671 (diff) | |
download | cpython-e4561e050148f6dc347e8c7ba30c8125b5fc0e45.zip cpython-e4561e050148f6dc347e8c7ba30c8125b5fc0e45.tar.gz cpython-e4561e050148f6dc347e8c7ba30c8125b5fc0e45.tar.bz2 |
gh-115778: Add `tierN` annotation for instruction definitions (#115815)
This replaces the old `TIER_{ONE,TWO}_ONLY` macros. Note that `specialized` implies `tier1`.
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Diffstat (limited to 'Tools/cases_generator')
-rw-r--r-- | Tools/cases_generator/analyzer.py | 15 | ||||
-rw-r--r-- | Tools/cases_generator/interpreter_definition.md | 1 | ||||
-rw-r--r-- | Tools/cases_generator/lexer.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/opcode_metadata_generator.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/tier2_abstract_generator.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/tier2_generator.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/uop_id_generator.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/uop_metadata_generator.py | 4 |
8 files changed, 20 insertions, 10 deletions
diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 49b8b42..b0a15e6 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -17,7 +17,6 @@ class Properties: needs_this: bool always_exits: bool stores_sp: bool - tier_one_only: bool uses_co_consts: bool uses_co_names: bool uses_locals: bool @@ -25,6 +24,7 @@ class Properties: side_exit: bool pure: bool passthrough: bool + tier: int | None = None oparg_and_1: bool = False const_oparg: int = -1 @@ -46,7 +46,6 @@ class Properties: needs_this=any(p.needs_this for p in properties), always_exits=any(p.always_exits for p in properties), stores_sp=any(p.stores_sp for p in properties), - tier_one_only=any(p.tier_one_only for p in properties), uses_co_consts=any(p.uses_co_consts for p in properties), uses_co_names=any(p.uses_co_names for p in properties), uses_locals=any(p.uses_locals for p in properties), @@ -68,7 +67,6 @@ SKIP_PROPERTIES = Properties( needs_this=False, always_exits=False, stores_sp=False, - tier_one_only=False, uses_co_consts=False, uses_co_names=False, uses_locals=False, @@ -312,6 +310,15 @@ def variable_used(node: parser.InstDef, name: str) -> bool: token.kind == "IDENTIFIER" and token.text == name for token in node.tokens ) +def tier_variable(node: parser.InstDef) -> int | None: + """Determine whether a tier variable is used in a node.""" + for token in node.tokens: + if token.kind == "ANNOTATION": + if token.text == "specializing": + return 1 + if re.fullmatch(r"tier\d", token.text): + return int(token.text[-1]) + return None def is_infallible(op: parser.InstDef) -> bool: return not ( @@ -498,7 +505,6 @@ def compute_properties(op: parser.InstDef) -> Properties: needs_this=variable_used(op, "this_instr"), always_exits=always_exits(op), stores_sp=variable_used(op, "SYNC_SP"), - tier_one_only=variable_used(op, "TIER_ONE_ONLY"), uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"), uses_co_names=variable_used(op, "FRAME_CO_NAMES"), uses_locals=(variable_used(op, "GETLOCAL") or variable_used(op, "SETLOCAL")) @@ -506,6 +512,7 @@ def compute_properties(op: parser.InstDef) -> Properties: has_free=has_free, pure="pure" in op.annotations, passthrough=passthrough, + tier=tier_variable(op), ) diff --git a/Tools/cases_generator/interpreter_definition.md b/Tools/cases_generator/interpreter_definition.md index 9b57335..889f58f 100644 --- a/Tools/cases_generator/interpreter_definition.md +++ b/Tools/cases_generator/interpreter_definition.md @@ -168,6 +168,7 @@ list of annotations and their meanings are as follows: * `override`. For external use by other interpreter definitions to override the current instruction definition. * `pure`. This instruction has no side effects. +* 'tierN'. This instruction only used by tier N interpreter. ### Special functions/macros diff --git a/Tools/cases_generator/lexer.py b/Tools/cases_generator/lexer.py index 0077921..13aee94 100644 --- a/Tools/cases_generator/lexer.py +++ b/Tools/cases_generator/lexer.py @@ -224,6 +224,8 @@ annotations = { "pure", "split", "replicate", + "tier1", + "tier2", } __all__ = [] diff --git a/Tools/cases_generator/opcode_metadata_generator.py b/Tools/cases_generator/opcode_metadata_generator.py index 24fbea6..ab59783 100644 --- a/Tools/cases_generator/opcode_metadata_generator.py +++ b/Tools/cases_generator/opcode_metadata_generator.py @@ -284,7 +284,7 @@ def is_viable_expansion(inst: Instruction) -> bool: continue if "replaced" in part.annotations: continue - if part.properties.tier_one_only or not part.is_viable(): + if part.properties.tier == 1 or not part.is_viable(): return False return True diff --git a/Tools/cases_generator/tier2_abstract_generator.py b/Tools/cases_generator/tier2_abstract_generator.py index 47a8626..58c3110 100644 --- a/Tools/cases_generator/tier2_abstract_generator.py +++ b/Tools/cases_generator/tier2_abstract_generator.py @@ -176,7 +176,7 @@ def generate_abstract_interpreter( if uop.name in abstract.uops: override = abstract.uops[uop.name] validate_uop(override, uop) - if uop.properties.tier_one_only: + if uop.properties.tier == 1: continue if uop.replicates: continue diff --git a/Tools/cases_generator/tier2_generator.py b/Tools/cases_generator/tier2_generator.py index 6fbe5c3..d8eed10 100644 --- a/Tools/cases_generator/tier2_generator.py +++ b/Tools/cases_generator/tier2_generator.py @@ -194,7 +194,7 @@ def generate_tier2( out = CWriter(outfile, 2, lines) out.emit("\n") for name, uop in analysis.uops.items(): - if uop.properties.tier_one_only: + if uop.properties.tier == 1: continue if uop.properties.oparg_and_1: out.emit(f"/* {uop.name} is split on (oparg & 1) */\n\n") diff --git a/Tools/cases_generator/uop_id_generator.py b/Tools/cases_generator/uop_id_generator.py index 907158f..eb5e3f4 100644 --- a/Tools/cases_generator/uop_id_generator.py +++ b/Tools/cases_generator/uop_id_generator.py @@ -43,7 +43,7 @@ def generate_uop_ids( for name, uop in sorted(uops): if name in PRE_DEFINED: continue - if uop.properties.tier_one_only: + if uop.properties.tier == 1: continue if uop.implicitly_created and not distinct_namespace and not uop.replicated: out.emit(f"#define {name} {name[1:]}\n") diff --git a/Tools/cases_generator/uop_metadata_generator.py b/Tools/cases_generator/uop_metadata_generator.py index f85f1c6..72eed30 100644 --- a/Tools/cases_generator/uop_metadata_generator.py +++ b/Tools/cases_generator/uop_metadata_generator.py @@ -29,7 +29,7 @@ def generate_names_and_flags(analysis: Analysis, out: CWriter) -> None: out.emit("#ifdef NEED_OPCODE_METADATA\n") out.emit("const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {\n") for uop in analysis.uops.values(): - if uop.is_viable() and not uop.properties.tier_one_only: + if uop.is_viable() and uop.properties.tier != 1: out.emit(f"[{uop.name}] = {cflags(uop.properties)},\n") out.emit("};\n\n") @@ -41,7 +41,7 @@ def generate_names_and_flags(analysis: Analysis, out: CWriter) -> None: out.emit("};\n\n") out.emit("const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {\n") for uop in sorted(analysis.uops.values(), key=lambda t: t.name): - if uop.is_viable() and not uop.properties.tier_one_only: + if uop.is_viable() and uop.properties.tier != 1: out.emit(f'[{uop.name}] = "{uop.name}",\n') out.emit("};\n") out.emit("#endif // NEED_OPCODE_METADATA\n\n") |