gh-106581: Split CALL_PY_EXACT_ARGS into uops (#107760)

* Split `CALL_PY_EXACT_ARGS` into uops

This is only the first step for doing `CALL` in Tier 2.
The next step involves tracing into the called code object and back.
After that we'll have to do the remaining `CALL` specialization.
Finally we'll have to deal with `KW_NAMES`.

Note: this moves setting `frame->return_offset` directly in front of
`DISPATCH_INLINED()`, to make it easier to move it into `_PUSH_FRAME`.
This commit is contained in:
Guido van Rossum 2023-08-16 16:26:43 -07:00 committed by GitHub
parent 665a4391e1
commit dc8fdf5fd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 412 additions and 116 deletions

View file

@ -25,6 +25,7 @@ from instructions import (
PseudoInstruction,
StackEffect,
OverriddenInstructionPlaceHolder,
TIER_ONE,
TIER_TWO,
)
import parsing
@ -65,6 +66,7 @@ OPARG_SIZES = {
"OPARG_CACHE_4": 4,
"OPARG_TOP": 5,
"OPARG_BOTTOM": 6,
"OPARG_SAVE_IP": 7,
}
INSTR_FMT_PREFIX = "INSTR_FMT_"
@ -501,7 +503,9 @@ class Generator(Analyzer):
if instr.kind == "inst" and instr.is_viable_uop():
# Construct a dummy Component -- input/output mappings are not used
part = Component(instr, instr.active_caches)
self.write_macro_expansions(instr.name, [part])
self.write_macro_expansions(
instr.name, [part], instr.cache_offset
)
elif instr.kind == "inst" and variable_used(
instr.inst, "oparg1"
):
@ -511,7 +515,9 @@ class Generator(Analyzer):
self.write_super_expansions(instr.name)
case parsing.Macro():
mac = self.macro_instrs[thing.name]
self.write_macro_expansions(mac.name, mac.parts)
self.write_macro_expansions(
mac.name, mac.parts, mac.cache_offset
)
case parsing.Pseudo():
pass
case _:
@ -630,7 +636,9 @@ class Generator(Analyzer):
if instr.kind == "op" and instr.is_viable_uop():
add(instr.name)
def write_macro_expansions(self, name: str, parts: MacroParts) -> None:
def write_macro_expansions(
self, name: str, parts: MacroParts, cache_offset: int
) -> None:
"""Write the macro expansions for a macro-instruction."""
# TODO: Refactor to share code with write_cody(), is_viaible_uop(), etc.
offset = 0 # Cache effect offset
@ -650,7 +658,10 @@ class Generator(Analyzer):
)
return
if not part.active_caches:
size, offset = OPARG_SIZES["OPARG_FULL"], 0
if part.instr.name == "SAVE_IP":
size, offset = OPARG_SIZES["OPARG_SAVE_IP"], cache_offset
else:
size, offset = OPARG_SIZES["OPARG_FULL"], 0
else:
# If this assert triggers, is_viable_uops() lied
assert len(part.active_caches) == 1, (name, part.instr.name)
@ -753,7 +764,9 @@ class Generator(Analyzer):
case parsing.Macro():
n_macros += 1
mac = self.macro_instrs[thing.name]
stacking.write_macro_instr(mac, self.out, self.families.get(mac.name))
stacking.write_macro_instr(
mac, self.out, self.families.get(mac.name)
)
# self.write_macro(self.macro_instrs[thing.name])
case parsing.Pseudo():
pass
@ -789,7 +802,9 @@ class Generator(Analyzer):
n_instrs += 1
self.out.emit("")
with self.out.block(f"case {thing.name}:"):
instr.write(self.out, tier=TIER_TWO)
stacking.write_single_instr(
instr, self.out, tier=TIER_TWO
)
if instr.check_eval_breaker:
self.out.emit("CHECK_EVAL_BREAKER();")
self.out.emit("break;")
@ -851,8 +866,13 @@ class Generator(Analyzer):
with self.out.block(f"TARGET({name})"):
if instr.predicted:
self.out.emit(f"PREDICTED({name});")
instr.write(self.out)
self.out.static_assert_family_size(
instr.name, instr.family, instr.cache_offset
)
stacking.write_single_instr(instr, self.out, tier=TIER_ONE)
if not instr.always_exits:
if instr.cache_offset:
self.out.emit(f"next_instr += {instr.cache_offset};")
if instr.check_eval_breaker:
self.out.emit("CHECK_EVAL_BREAKER();")
self.out.emit(f"DISPATCH();")