Skip to content

Commit cc25ca1

Browse files
authored
gh-106706: Streamline family syntax in cases generator DSL (#106716)
From `family(opname, STRUCTSIZE) = OPNAME + SPEC1 + ... + SPECn;` to `family(OPNAME, STRUCTSIZE) = SPEC1 + ... + SPECn;`
1 parent e589601 commit cc25ca1

File tree

5 files changed

+31
-42
lines changed

5 files changed

+31
-42
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Change bytecode syntax for families
2+
to remove redundant name matching
3+
pseudo syntax.

Python/bytecodes.c

+13-26
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,7 @@ dummy_func(
284284
res = Py_IsFalse(value) ? Py_True : Py_False;
285285
}
286286

287-
family(to_bool, INLINE_CACHE_ENTRIES_TO_BOOL) = {
288-
TO_BOOL,
287+
family(TO_BOOL, INLINE_CACHE_ENTRIES_TO_BOOL) = {
289288
TO_BOOL_ALWAYS_TRUE,
290289
TO_BOOL_BOOL,
291290
TO_BOOL_INT,
@@ -372,8 +371,7 @@ dummy_func(
372371
ERROR_IF(res == NULL, error);
373372
}
374373

375-
family(binary_op, INLINE_CACHE_ENTRIES_BINARY_OP) = {
376-
BINARY_OP,
374+
family(BINARY_OP, INLINE_CACHE_ENTRIES_BINARY_OP) = {
377375
BINARY_OP_MULTIPLY_INT,
378376
BINARY_OP_ADD_INT,
379377
BINARY_OP_SUBTRACT_INT,
@@ -507,8 +505,7 @@ dummy_func(
507505
macro(BINARY_OP_INPLACE_ADD_UNICODE) =
508506
_GUARD_BOTH_UNICODE + _BINARY_OP_INPLACE_ADD_UNICODE;
509507

510-
family(binary_subscr, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
511-
BINARY_SUBSCR,
508+
family(BINARY_SUBSCR, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
512509
BINARY_SUBSCR_DICT,
513510
BINARY_SUBSCR_GETITEM,
514511
BINARY_SUBSCR_LIST_INT,
@@ -643,8 +640,7 @@ dummy_func(
643640
ERROR_IF(err, error);
644641
}
645642

646-
family(store_subscr, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = {
647-
STORE_SUBSCR,
643+
family(STORE_SUBSCR, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = {
648644
STORE_SUBSCR_DICT,
649645
STORE_SUBSCR_LIST_INT,
650646
};
@@ -921,8 +917,7 @@ dummy_func(
921917
ERROR_IF(iter == NULL, error);
922918
}
923919

924-
family(send, INLINE_CACHE_ENTRIES_SEND) = {
925-
SEND,
920+
family(SEND, INLINE_CACHE_ENTRIES_SEND) = {
926921
SEND_GEN,
927922
};
928923

@@ -1134,8 +1129,7 @@ dummy_func(
11341129
}
11351130
}
11361131

1137-
family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = {
1138-
UNPACK_SEQUENCE,
1132+
family(UNPACK_SEQUENCE, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = {
11391133
UNPACK_SEQUENCE_TWO_TUPLE,
11401134
UNPACK_SEQUENCE_TUPLE,
11411135
UNPACK_SEQUENCE_LIST,
@@ -1198,8 +1192,7 @@ dummy_func(
11981192
ERROR_IF(res == 0, error);
11991193
}
12001194

1201-
family(store_attr, INLINE_CACHE_ENTRIES_STORE_ATTR) = {
1202-
STORE_ATTR,
1195+
family(STORE_ATTR, INLINE_CACHE_ENTRIES_STORE_ATTR) = {
12031196
STORE_ATTR_INSTANCE_VALUE,
12041197
STORE_ATTR_SLOT,
12051198
STORE_ATTR_WITH_HINT,
@@ -1298,8 +1291,7 @@ dummy_func(
12981291

12991292
macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS;
13001293

1301-
family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
1302-
LOAD_GLOBAL,
1294+
family(LOAD_GLOBAL, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
13031295
LOAD_GLOBAL_MODULE,
13041296
LOAD_GLOBAL_BUILTIN,
13051297
};
@@ -1647,8 +1639,7 @@ dummy_func(
16471639
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
16481640
}
16491641

1650-
family(load_super_attr, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
1651-
LOAD_SUPER_ATTR,
1642+
family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
16521643
LOAD_SUPER_ATTR_ATTR,
16531644
LOAD_SUPER_ATTR_METHOD,
16541645
};
@@ -1750,8 +1741,7 @@ dummy_func(
17501741
}
17511742
}
17521743

1753-
family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {
1754-
LOAD_ATTR,
1744+
family(LOAD_ATTR, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {
17551745
LOAD_ATTR_INSTANCE_VALUE,
17561746
LOAD_ATTR_MODULE,
17571747
LOAD_ATTR_WITH_HINT,
@@ -2048,8 +2038,7 @@ dummy_func(
20482038
Py_DECREF(owner);
20492039
}
20502040

2051-
family(compare_op, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
2052-
COMPARE_OP,
2041+
family(COMPARE_OP, INLINE_CACHE_ENTRIES_COMPARE_OP) = {
20532042
COMPARE_OP_FLOAT,
20542043
COMPARE_OP_INT,
20552044
COMPARE_OP_STR,
@@ -2350,8 +2339,7 @@ dummy_func(
23502339
// This is optimized by skipping that instruction and combining
23512340
// its effect (popping 'iter' instead of pushing 'next'.)
23522341

2353-
family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = {
2354-
FOR_ITER,
2342+
family(FOR_ITER, INLINE_CACHE_ENTRIES_FOR_ITER) = {
23552343
FOR_ITER_LIST,
23562344
FOR_ITER_TUPLE,
23572345
FOR_ITER_RANGE,
@@ -2810,8 +2798,7 @@ dummy_func(
28102798

28112799
// Cache layout: counter/1, func_version/2
28122800
// Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
2813-
family(call, INLINE_CACHE_ENTRIES_CALL) = {
2814-
CALL,
2801+
family(CALL, INLINE_CACHE_ENTRIES_CALL) = {
28152802
CALL_BOUND_METHOD_EXACT_ARGS,
28162803
CALL_PY_EXACT_ARGS,
28172804
CALL_PY_WITH_DEFAULTS,

Tools/cases_generator/generate_cases.py

+13-14
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def write(self, out: Formatter, tier: Tiers = TIER_ONE) -> None:
438438
"""Write one instruction, sans prologue and epilogue."""
439439
# Write a static assertion that a family's cache size is correct
440440
if family := self.family:
441-
if self.name == family.members[0]:
441+
if self.name == family.name:
442442
if cache_size := family.size:
443443
out.emit(
444444
f"static_assert({cache_size} == "
@@ -831,7 +831,7 @@ def find_predictions(self) -> None:
831831
def map_families(self) -> None:
832832
"""Link instruction names back to their family, if they have one."""
833833
for family in self.families.values():
834-
for member in family.members:
834+
for member in [family.name] + family.members:
835835
if member_instr := self.instrs.get(member):
836836
if member_instr.family not in (family, None):
837837
self.error(
@@ -855,8 +855,11 @@ def check_families(self) -> None:
855855
- All members must have the same cache, input and output effects
856856
"""
857857
for family in self.families.values():
858-
if len(family.members) < 2:
859-
self.error(f"Family {family.name!r} has insufficient members", family)
858+
if family.name not in self.macro_instrs and family.name not in self.instrs:
859+
self.error(
860+
f"Family {family.name!r} has unknown instruction {family.name!r}",
861+
family,
862+
)
860863
members = [
861864
member
862865
for member in family.members
@@ -867,10 +870,8 @@ def check_families(self) -> None:
867870
self.error(
868871
f"Family {family.name!r} has unknown members: {unknown}", family
869872
)
870-
if len(members) < 2:
871-
continue
872-
expected_effects = self.effect_counts(members[0])
873-
for member in members[1:]:
873+
expected_effects = self.effect_counts(family.name)
874+
for member in members:
874875
member_effects = self.effect_counts(member)
875876
if member_effects != expected_effects:
876877
self.error(
@@ -1311,11 +1312,10 @@ def write_metadata(self) -> None:
13111312
self.out.emit("")
13121313
self.out.emit("_specializations = {")
13131314
for name, family in self.families.items():
1314-
assert len(family.members) > 1
13151315
with self.out.indent():
1316-
self.out.emit(f"\"{family.members[0]}\": [")
1316+
self.out.emit(f"\"{family.name}\": [")
13171317
with self.out.indent():
1318-
for m in family.members[1:]:
1318+
for m in family.members:
13191319
self.out.emit(f"\"{m}\",")
13201320
self.out.emit(f"],")
13211321
self.out.emit("}")
@@ -1551,9 +1551,8 @@ def write_macro(self, mac: MacroInstruction) -> None:
15511551
self.out.emit(f"next_instr += {cache_adjust};")
15521552

15531553
if (
1554-
last_instr
1555-
and (family := last_instr.family)
1556-
and mac.name == family.members[0]
1554+
(family := self.families.get(mac.name))
1555+
and mac.name == family.name
15571556
and (cache_size := family.size)
15581557
):
15591558
self.out.emit(

Tools/cases_generator/interpreter_definition.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ For explanations see "Generating the interpreter" below.)
347347

348348
### Defining an instruction family
349349

350-
A _family_ represents a specializable instruction and its specializations.
350+
A _family_ maps a specializable instruction to its specializations.
351351

352352
Example: These opcodes all share the same instruction format):
353353
```C

Tools/cases_generator/test_generator.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def test_macro_instruction():
287287
inst(OP3, (unused/5, arg2, left, right -- res)) {
288288
res = op3(arg2, left, right);
289289
}
290-
family(op, INLINE_CACHE_ENTRIES_OP) = { OP, OP3 };
290+
family(OP, INLINE_CACHE_ENTRIES_OP) = { OP3 };
291291
"""
292292
output = """
293293
TARGET(OP1) {

0 commit comments

Comments
 (0)