Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-106812: Refactor to allow uops with array stack effects #107564

Merged
merged 39 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
67d0445
Make repr(StackEffect()) nicer
gvanrossum Jul 23, 2023
f8a56f9
Ignore name when comparing StackEffect
gvanrossum Jul 23, 2023
2e80b55
Improve counting of things read/written
gvanrossum Jul 25, 2023
c2f4277
Record which instructions use DEOPT_IF
gvanrossum Jul 29, 2023
80f2895
Blackify a few turds left by refactor
gvanrossum Jul 30, 2023
41878fe
Add warning() and note() helpers
gvanrossum Jul 31, 2023
4ad5db2
Use self.note() for non-viable uops in macros
gvanrossum Jul 31, 2023
9a0bdb1
Temporary check for troublesome macros
gvanrossum Jul 31, 2023
d989f6b
Replace part of Instruction.write()
gvanrossum Jul 31, 2023
533fe6b
Replace most of the rest of Instruction.write()
gvanrossum Jul 31, 2023
d92516c
Spread enum InstructionFormat across multiple lines
gvanrossum Aug 1, 2023
ce14682
Compute macro stack effect info using stacking.py
gvanrossum Aug 1, 2023
d067e45
Disappear wrap_macro
gvanrossum Aug 1, 2023
5437eca
Add helper method to Formatter for family size static assert
gvanrossum Aug 1, 2023
dbc04f8
Replace write_macro with stacking logic
gvanrossum Aug 1, 2023
cf46cc2
Emit cache vars in macros
gvanrossum Aug 2, 2023
c979089
Increment next_instr in macros
gvanrossum Aug 2, 2023
c41c906
Move conditional init test to Formatter.declare()
gvanrossum Aug 2, 2023
cfb5bcb
Fix bug in merge(); clean up a bit
gvanrossum Aug 2, 2023
4cb3986
Fix test_generated_cases.py
gvanrossum Aug 2, 2023
51e3e29
Unify Peek/Poke to StackItem
gvanrossum Aug 2, 2023
2195484
Get rid of initial_offset and net_offset (unused)
gvanrossum Aug 2, 2023
aa9832a
Refactor write_macro_instr
gvanrossum Aug 2, 2023
3027ccb
Unify macro and single instruction writing
gvanrossum Aug 2, 2023
597b97f
Skip pokes for unmoved names
gvanrossum Aug 2, 2023
ce6c203
Fix tests
gvanrossum Aug 2, 2023
dde4595
Add static_assert back to macro
gvanrossum Aug 2, 2023
8e96cc1
Remove some unneeded imports and commented-out code
gvanrossum Aug 2, 2023
652093c
Fix test by moving import
gvanrossum Aug 2, 2023
d21f8a4
Rm {in,out}put_mapping, stack, {initial,final}_sp
gvanrossum Aug 2, 2023
008721c
Make StackOffset a member instead of base class of StackItem
gvanrossum Aug 2, 2023
b4a9652
Fix type errors
gvanrossum Aug 2, 2023
777bbd4
Move merge into __init__; offset includes effect
gvanrossum Aug 2, 2023
7c930e3
Simplify get_stack_effect_info_for_macro
gvanrossum Aug 3, 2023
0ff94ac
Remove unused import of abstractmethod
gvanrossum Aug 3, 2023
39051e3
Improve consistency errors; rm stack_analysis()
gvanrossum Aug 3, 2023
09a40fa
Add asserts for push/pop above stack level
gvanrossum Aug 3, 2023
925388f
Improve asserts for push/pop above stack level
gvanrossum Aug 3, 2023
bb56748
Remove unused def string_effect_size and tests
gvanrossum Aug 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions Include/internal/pycore_opcode_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,9 +679,9 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
case LOAD_GLOBAL:
return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_GLOBAL_MODULE:
return ((oparg & 1) ? 1 : 0) + 1;
return (oparg & 1 ? 1 : 0) + 1;
case LOAD_GLOBAL_BUILTIN:
return ((oparg & 1) ? 1 : 0) + 1;
return (oparg & 1 ? 1 : 0) + 1;
case DELETE_FAST:
return 0;
case MAKE_CELL:
Expand Down Expand Up @@ -739,7 +739,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
case LOAD_METHOD:
return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_ATTR_INSTANCE_VALUE:
return ((oparg & 1) ? 1 : 0) + 1;
return (oparg & 1 ? 1 : 0) + 1;
case LOAD_ATTR_MODULE:
return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_ATTR_WITH_HINT:
Expand Down Expand Up @@ -944,7 +944,18 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
}
#endif

enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC00, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC0, INSTR_FMT_IXC00, INSTR_FMT_IXC000 };
enum InstructionFormat {
INSTR_FMT_IB,
INSTR_FMT_IBC,
INSTR_FMT_IBC00,
INSTR_FMT_IBC000,
INSTR_FMT_IBC00000000,
INSTR_FMT_IX,
INSTR_FMT_IXC,
INSTR_FMT_IXC0,
INSTR_FMT_IXC00,
INSTR_FMT_IXC000,
};

#define IS_VALID_OPCODE(OP) \
(((OP) >= 0) && ((OP) < OPCODE_METADATA_SIZE) && \
Expand Down
158 changes: 81 additions & 77 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

test_tools.skip_if_missing('cases_generator')
with test_tools.imports_under_tool('cases_generator'):
import generate_cases
import analysis
import formatting
import generate_cases
from parsing import StackEffect


Expand Down Expand Up @@ -46,28 +46,11 @@ def test_effect_sizes(self):
(2, "(oparg<<1)"),
)

self.assertEqual(
formatting.string_effect_size(
formatting.list_effect_size(input_effects),
), "1 + oparg + oparg*2",
)
self.assertEqual(
formatting.string_effect_size(
formatting.list_effect_size(output_effects),
),
"2 + oparg*4",
)
self.assertEqual(
formatting.string_effect_size(
formatting.list_effect_size(other_effects),
),
"2 + (oparg<<1)",
)


class TestGeneratedCases(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
self.maxDiff = None

self.temp_dir = tempfile.gettempdir()
self.temp_input_filename = os.path.join(self.temp_dir, "input.txt")
Expand Down Expand Up @@ -140,7 +123,8 @@ def test_inst_one_pop(self):
"""
output = """
TARGET(OP) {
PyObject *value = stack_pointer[-1];
PyObject *value;
value = stack_pointer[-1];
spam();
STACK_SHRINK(1);
DISPATCH();
Expand Down Expand Up @@ -173,8 +157,9 @@ def test_inst_one_push_one_pop(self):
"""
output = """
TARGET(OP) {
PyObject *value = stack_pointer[-1];
PyObject *value;
PyObject *res;
value = stack_pointer[-1];
spam();
stack_pointer[-1] = res;
DISPATCH();
Expand All @@ -190,9 +175,11 @@ def test_binary_op(self):
"""
output = """
TARGET(OP) {
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *right;
PyObject *left;
PyObject *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
spam();
STACK_SHRINK(1);
stack_pointer[-1] = res;
Expand All @@ -209,9 +196,11 @@ def test_overlap(self):
"""
output = """
TARGET(OP) {
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *right;
PyObject *left;
PyObject *result;
right = stack_pointer[-1];
left = stack_pointer[-2];
spam();
stack_pointer[-1] = result;
DISPATCH();
Expand All @@ -235,8 +224,9 @@ def test_predictions_and_eval_breaker(self):
}

TARGET(OP3) {
PyObject *arg = stack_pointer[-1];
PyObject *arg;
PyObject *res;
arg = stack_pointer[-1];
DEOPT_IF(xxx, OP1);
stack_pointer[-1] = res;
CHECK_EVAL_BREAKER();
Expand Down Expand Up @@ -281,9 +271,11 @@ def test_error_if_pop(self):
"""
output = """
TARGET(OP) {
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *right;
PyObject *left;
PyObject *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (cond) goto pop_2_label;
STACK_SHRINK(1);
stack_pointer[-1] = res;
Expand All @@ -299,7 +291,8 @@ def test_cache_effect(self):
"""
output = """
TARGET(OP) {
PyObject *value = stack_pointer[-1];
PyObject *value;
value = stack_pointer[-1];
uint16_t counter = read_u16(&next_instr[0].cache);
uint32_t extra = read_u32(&next_instr[1].cache);
STACK_SHRINK(1);
Expand Down Expand Up @@ -338,47 +331,49 @@ def test_macro_instruction(self):
"""
output = """
TARGET(OP1) {
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *right;
PyObject *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
uint16_t counter = read_u16(&next_instr[0].cache);
op1(left, right);
next_instr += 1;
DISPATCH();
}

TARGET(OP) {
PyObject *_tmp_1 = stack_pointer[-1];
PyObject *_tmp_2 = stack_pointer[-2];
PyObject *_tmp_3 = stack_pointer[-3];
static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");
PyObject *right;
PyObject *left;
PyObject *arg2;
PyObject *res;
// OP1
right = stack_pointer[-1];
left = stack_pointer[-2];
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
uint16_t counter = read_u16(&next_instr[0].cache);
op1(left, right);
_tmp_2 = left;
_tmp_1 = right;
}
// OP2
arg2 = stack_pointer[-3];
{
PyObject *right = _tmp_1;
PyObject *left = _tmp_2;
PyObject *arg2 = _tmp_3;
PyObject *res;
uint32_t extra = read_u32(&next_instr[3].cache);
res = op2(arg2, left, right);
_tmp_3 = res;
}
next_instr += 5;
static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");
STACK_SHRINK(2);
stack_pointer[-1] = _tmp_3;
stack_pointer[-1] = res;
next_instr += 5;
DISPATCH();
}

TARGET(OP3) {
PyObject *right = stack_pointer[-1];
PyObject *left = stack_pointer[-2];
PyObject *arg2 = stack_pointer[-3];
PyObject *right;
PyObject *left;
PyObject *arg2;
PyObject *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
arg2 = stack_pointer[-3];
res = op3(arg2, left, right);
STACK_SHRINK(2);
stack_pointer[-1] = res;
Expand All @@ -396,9 +391,12 @@ def test_array_input(self):
"""
output = """
TARGET(OP) {
PyObject *above = stack_pointer[-1];
PyObject **values = (stack_pointer - (1 + oparg*2));
PyObject *below = stack_pointer[-(2 + oparg*2)];
PyObject *above;
PyObject **values;
PyObject *below;
above = stack_pointer[-1];
values = stack_pointer - 1 - oparg*2;
below = stack_pointer[-2 - oparg*2];
spam();
STACK_SHRINK(oparg*2);
STACK_SHRINK(2);
Expand All @@ -416,12 +414,13 @@ def test_array_output(self):
output = """
TARGET(OP) {
PyObject *below;
PyObject **values = stack_pointer - (2) + 1;
PyObject **values;
PyObject *above;
values = stack_pointer - 1;
spam(values, oparg);
STACK_GROW(oparg*3);
stack_pointer[-2 - oparg*3] = below;
stack_pointer[-1] = above;
stack_pointer[-(2 + oparg*3)] = below;
DISPATCH();
}
"""
Expand All @@ -435,8 +434,9 @@ def test_array_input_output(self):
"""
output = """
TARGET(OP) {
PyObject **values = (stack_pointer - oparg);
PyObject **values;
PyObject *above;
values = stack_pointer - oparg;
spam(values, oparg);
STACK_GROW(1);
stack_pointer[-1] = above;
Expand All @@ -453,8 +453,10 @@ def test_array_error_if(self):
"""
output = """
TARGET(OP) {
PyObject **values = (stack_pointer - oparg);
PyObject *extra = stack_pointer[-(1 + oparg)];
PyObject **values;
PyObject *extra;
values = stack_pointer - oparg;
extra = stack_pointer[-1 - oparg];
if (oparg == 0) { STACK_SHRINK(oparg); goto pop_1_somewhere; }
STACK_SHRINK(oparg);
STACK_SHRINK(1);
Expand All @@ -471,18 +473,21 @@ def test_cond_effect(self):
"""
output = """
TARGET(OP) {
PyObject *cc = stack_pointer[-1];
PyObject *input = ((oparg & 1) == 1) ? stack_pointer[-(1 + (((oparg & 1) == 1) ? 1 : 0))] : NULL;
PyObject *aa = stack_pointer[-(2 + (((oparg & 1) == 1) ? 1 : 0))];
PyObject *cc;
PyObject *input = NULL;
PyObject *aa;
PyObject *xx;
PyObject *output = NULL;
PyObject *zz;
cc = stack_pointer[-1];
if ((oparg & 1) == 1) { input = stack_pointer[-1 - ((oparg & 1) == 1 ? 1 : 0)]; }
aa = stack_pointer[-2 - ((oparg & 1) == 1 ? 1 : 0)];
output = spam(oparg, input);
STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0));
STACK_GROW(((oparg & 2) ? 1 : 0));
stack_pointer[-2 - (oparg & 2 ? 1 : 0)] = xx;
if (oparg & 2) { stack_pointer[-1 - (oparg & 2 ? 1 : 0)] = output; }
stack_pointer[-1] = zz;
if (oparg & 2) { stack_pointer[-(1 + ((oparg & 2) ? 1 : 0))] = output; }
stack_pointer[-(2 + ((oparg & 2) ? 1 : 0))] = xx;
DISPATCH();
}
"""
Expand All @@ -500,29 +505,28 @@ def test_macro_cond_effect(self):
"""
output = """
TARGET(M) {
PyObject *_tmp_1 = stack_pointer[-1];
PyObject *_tmp_2 = stack_pointer[-2];
PyObject *_tmp_3 = stack_pointer[-3];
PyObject *right;
PyObject *middle;
PyObject *left;
PyObject *deep;
PyObject *extra = NULL;
PyObject *res;
// A
right = stack_pointer[-1];
middle = stack_pointer[-2];
left = stack_pointer[-3];
{
PyObject *right = _tmp_1;
PyObject *middle = _tmp_2;
PyObject *left = _tmp_3;
# Body of A
}
// B
{
PyObject *deep;
PyObject *extra = NULL;
PyObject *res;
# Body of B
_tmp_3 = deep;
if (oparg) { _tmp_2 = extra; }
_tmp_1 = res;
}
STACK_SHRINK(1);
STACK_GROW((oparg ? 1 : 0));
stack_pointer[-1] = _tmp_1;
if (oparg) { stack_pointer[-2] = _tmp_2; }
stack_pointer[-3] = _tmp_3;
stack_pointer[-2 - (oparg ? 1 : 0)] = deep;
if (oparg) { stack_pointer[-1 - (oparg ? 1 : 0)] = extra; }
stack_pointer[-1] = res;
DISPATCH();
}
"""
Expand Down
Loading
Loading