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-120619: Tier 2 partial evaluator foundations #124910

Open
wants to merge 54 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
48f024b
skeleton
Fidget-Spinner Sep 1, 2024
dd5cfe7
generate the pe from the base optimizer
Fidget-Spinner Sep 2, 2024
2d6884d
cleanup
Fidget-Spinner Sep 2, 2024
e5e7364
basic copying setup
Fidget-Spinner Sep 2, 2024
9722b40
fix compilation
Fidget-Spinner Sep 3, 2024
d8732fc
baby pe
Fidget-Spinner Sep 3, 2024
a6bc1a0
dead store elimination
Fidget-Spinner Sep 3, 2024
6a6dbce
cleanup
Fidget-Spinner Sep 3, 2024
7562c75
Create 2024-09-04-03-36-48.gh-issue-120619.yE7lQb.rst
Fidget-Spinner Sep 3, 2024
5200bce
fix tests
Fidget-Spinner Sep 3, 2024
db31411
Merge remote-tracking branch 'upstream/main' into partial_evaluator
Fidget-Spinner Sep 13, 2024
23e4b7c
Update partial_evaluator_cases.c.h
Fidget-Spinner Sep 13, 2024
06e6fcd
Merge remote-tracking branch 'upstream/main' into partial_evaluator
Fidget-Spinner Sep 15, 2024
0a1d12e
Update partial_evaluator_cases.c.h
Fidget-Spinner Sep 15, 2024
bfbf608
reorder reifications
Fidget-Spinner Sep 15, 2024
8fe279e
fix c-analzyer
Fidget-Spinner Sep 15, 2024
4361821
remove static, remove some pure
Fidget-Spinner Sep 17, 2024
5df786d
Revert "remove static, remove some pure"
Fidget-Spinner Sep 17, 2024
e8b402f
make LOAD_CONST static as well
Fidget-Spinner Sep 17, 2024
a73a5c2
Merge remote-tracking branch 'upstream/main' into partial_evaluator
Fidget-Spinner Oct 2, 2024
d7d2c3c
fixup
Fidget-Spinner Oct 2, 2024
9a89865
cleanup
Fidget-Spinner Oct 2, 2024
471d45f
Use the other architecture
Fidget-Spinner Oct 2, 2024
9a167be
Cleanup
Fidget-Spinner Oct 2, 2024
ee5cf74
Merge remote-tracking branch 'upstream/main' into partial_evaluator_2
Fidget-Spinner Oct 2, 2024
0b0f83f
Update partial_evaluator_cases.c.h
Fidget-Spinner Oct 2, 2024
54b9057
Revert changes to optimizer
Fidget-Spinner Oct 3, 2024
cea3f2c
Create separate pe files
Fidget-Spinner Oct 3, 2024
a4e13d4
add sourcefile and makefile
Fidget-Spinner Oct 3, 2024
32057d9
fix up compile problems
Fidget-Spinner Oct 3, 2024
6cd8a8c
fix compilation
Fidget-Spinner Oct 3, 2024
8477c5a
fix rest
Fidget-Spinner Oct 3, 2024
d2b0d82
fix everything for real
Fidget-Spinner Oct 3, 2024
96d371e
partially address review
Fidget-Spinner Oct 3, 2024
1b028a0
turn JIT back on
Fidget-Spinner Oct 3, 2024
865bd26
fix Windows build
Fidget-Spinner Oct 3, 2024
1fb6792
Fix c analyzer
Fidget-Spinner Oct 3, 2024
365082f
Address review
Fidget-Spinner Oct 11, 2024
06d5311
Merge remote-tracking branch 'upstream/main' into partial_evaluator_2
Fidget-Spinner Oct 11, 2024
b2f4fa6
update
Fidget-Spinner Oct 11, 2024
195bb88
fix problems from merge
Fidget-Spinner Oct 11, 2024
5c57743
fix mypy
Fidget-Spinner Oct 11, 2024
3b02478
fix thing
Fidget-Spinner Oct 11, 2024
4985d3f
Fix mypy signature
Fidget-Spinner Oct 12, 2024
71ace95
Merge remote-tracking branch 'upstream/main' into partial_evaluator_2
Fidget-Spinner Oct 30, 2024
8c45921
fix upstream merge
Fidget-Spinner Oct 30, 2024
67be67a
Add tests
Fidget-Spinner Oct 30, 2024
5ee455e
Delete 2024-09-04-03-36-48.gh-issue-120619.yE7lQb.rst
Fidget-Spinner Oct 30, 2024
9d8e574
📜🤖 Added by blurb_it.
blurb-it[bot] Oct 30, 2024
a61c275
Merge remote-tracking branch 'upstream/main' into partial_evaluator_2
Fidget-Spinner Nov 4, 2024
aa5f8c2
fix build problems
Fidget-Spinner Nov 4, 2024
62f1679
Merge remote-tracking branch 'upstream/main' into partial_evaluator_2
Fidget-Spinner Dec 4, 2024
9348115
Fix changes from upstream
Fidget-Spinner Dec 4, 2024
8270def
Update test_opt.py
Fidget-Spinner Dec 4, 2024
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
20 changes: 11 additions & 9 deletions Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 42 additions & 27 deletions Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef struct {
};
};
uint64_t operand; // A cache entry
char is_virtual; // Used by tier 2 optimizer.
} _PyUOpInstruction;

typedef struct {
Expand Down Expand Up @@ -165,6 +166,7 @@ struct _Py_UopsSymbol {
#define UOP_FORMAT_TARGET 0
#define UOP_FORMAT_JUMP 1


static inline uint32_t uop_get_target(const _PyUOpInstruction *inst)
{
assert(inst->format == UOP_FORMAT_TARGET);
Expand Down Expand Up @@ -199,14 +201,21 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)

typedef struct _Py_UopsSymbol _Py_UopsSymbol;

typedef struct _Py_UopsLocalsPlusSlot {
_Py_UopsSymbol *sym;
_PyUOpInstruction *origin_inst; // The instruction this symbol originates from.
} _Py_UopsLocalsPlusSlot;

struct _Py_UOpsAbstractFrame {
// Max stacklen
int stack_len;
int locals_len;

_Py_UopsSymbol **stack_pointer;
_Py_UopsSymbol **stack;
_Py_UopsSymbol **locals;
_Py_UopsLocalsPlusSlot *stack_pointer;
_Py_UopsLocalsPlusSlot *stack;
_Py_UopsLocalsPlusSlot *locals;

void *instr_ptr;
};

typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
Expand All @@ -229,34 +238,40 @@ struct _Py_UOpsContext {
// Arena for the symbolic types.
ty_arena t_arena;

_Py_UopsSymbol **n_consumed;
_Py_UopsSymbol **limit;
_Py_UopsSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
_Py_UopsLocalsPlusSlot *n_consumed;
_Py_UopsLocalsPlusSlot *limit;
_Py_UopsLocalsPlusSlot locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];

_PyUOpInstruction *trace_dest;
int n_trace_dest;
};

typedef struct _Py_UOpsContext _Py_UOpsContext;

extern bool _Py_uop_sym_is_null(_Py_UopsSymbol *sym);
extern bool _Py_uop_sym_is_not_null(_Py_UopsSymbol *sym);
extern bool _Py_uop_sym_is_const(_Py_UopsSymbol *sym);
extern PyObject *_Py_uop_sym_get_const(_Py_UopsSymbol *sym);
extern _Py_UopsSymbol *_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx);
extern _Py_UopsSymbol *_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx);
extern _Py_UopsSymbol *_Py_uop_sym_new_type(
extern bool _Py_uop_sym_is_null(_Py_UopsLocalsPlusSlot sym);
extern bool _Py_uop_sym_is_not_null(_Py_UopsLocalsPlusSlot sym);
extern bool _Py_uop_sym_is_const(_Py_UopsLocalsPlusSlot sym);
extern PyObject *_Py_uop_sym_get_const(_Py_UopsLocalsPlusSlot sym);
extern _Py_UopsLocalsPlusSlot _Py_uop_sym_new_unknown(_Py_UOpsContext *ctx);
extern _Py_UopsLocalsPlusSlot _Py_uop_sym_new_not_null(_Py_UOpsContext *ctx);
extern _Py_UopsLocalsPlusSlot _Py_uop_sym_new_type(
_Py_UOpsContext *ctx, PyTypeObject *typ);
extern _Py_UopsSymbol *_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val);
extern _Py_UopsSymbol *_Py_uop_sym_new_null(_Py_UOpsContext *ctx);
extern bool _Py_uop_sym_has_type(_Py_UopsSymbol *sym);
extern bool _Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ);
extern bool _Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version);
extern void _Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
extern void _Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
extern void _Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ);
extern bool _Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version);
extern void _Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val);
extern bool _Py_uop_sym_is_bottom(_Py_UopsSymbol *sym);
extern int _Py_uop_sym_truthiness(_Py_UopsSymbol *sym);
extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsSymbol *sym);
extern _Py_UopsLocalsPlusSlot _Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val);
extern _Py_UopsLocalsPlusSlot _Py_uop_sym_new_null(_Py_UOpsContext *ctx);
extern bool _Py_uop_sym_has_type(_Py_UopsLocalsPlusSlot sym);
extern bool _Py_uop_sym_matches_type(_Py_UopsLocalsPlusSlot sym, PyTypeObject *typ);
extern bool _Py_uop_sym_matches_type_version(_Py_UopsLocalsPlusSlot sym, unsigned int version);
extern void _Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsLocalsPlusSlot sym);
extern void _Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsLocalsPlusSlot sym);
extern void _Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsLocalsPlusSlot sym, PyTypeObject *typ);
extern bool _Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsLocalsPlusSlot sym, unsigned int version);
extern void _Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsLocalsPlusSlot sym, PyObject *const_val);
extern bool _Py_uop_sym_is_bottom(_Py_UopsLocalsPlusSlot sym);
extern int _Py_uop_sym_truthiness(_Py_UopsLocalsPlusSlot sym);
extern void _Py_uop_sym_set_origin_inst_override(_Py_UopsLocalsPlusSlot *sym, _PyUOpInstruction *origin);
extern bool _Py_uop_sym_is_virtual(_Py_UopsLocalsPlusSlot sym);
extern _PyUOpInstruction *_Py_uop_sym_get_origin(_Py_UopsLocalsPlusSlot sym);
extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsLocalsPlusSlot sym);


extern void _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx);
Expand All @@ -266,7 +281,7 @@ extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
_Py_UOpsContext *ctx,
PyCodeObject *co,
int curr_stackentries,
_Py_UopsSymbol **args,
_Py_UopsLocalsPlusSlot *args,
int arg_len);
extern int _Py_uop_frame_pop(_Py_UOpsContext *ctx);

Expand Down
44 changes: 22 additions & 22 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,33 @@ def fn(a):

fn(A())

def test_pe_load_fast_pop_top(self):
def thing(a):
x = 0
for i in range(20):
i
return i


res, ex = self._run_with_optimizer(thing, 1)
self.assertEqual(res, 19)
self.assertIsNotNone(ex)
self.assertEqual(list(iter_opnames(ex)).count("_POP_TOP"), 0)
self.assertTrue(ex.is_valid())

def test_pe_dead_store_elimination(self):
def thing(a):
x = 0
for i in range(20):
x = x
return i


res, ex = self._run_with_optimizer(thing, 1)
self.assertEqual(res, 19)
self.assertIsNotNone(ex)
self.assertEqual(list(iter_opnames(ex)).count("_LOAD_FAST_1"), 0)
self.assertTrue(ex.is_valid())

if __name__ == "__main__":
unittest.main()
12 changes: 6 additions & 6 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -1264,15 +1264,15 @@ def test_overridden_abstract_args(self):
"""
output = """
case OP: {
_Py_UopsSymbol *arg1;
_Py_UopsSymbol *out;
_Py_UopsLocalsPlusSlot arg1;
_Py_UopsLocalsPlusSlot out;
eggs();
stack_pointer[-1] = out;
break;
}

case OP2: {
_Py_UopsSymbol *out;
_Py_UopsLocalsPlusSlot out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
Expand All @@ -1296,15 +1296,15 @@ def test_no_overridden_case(self):
"""
output = """
case OP: {
_Py_UopsSymbol *out;
_Py_UopsLocalsPlusSlot out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
}

case OP2: {
_Py_UopsSymbol *arg1;
_Py_UopsSymbol *out;
_Py_UopsLocalsPlusSlot arg1;
_Py_UopsLocalsPlusSlot out;
stack_pointer[-1] = out;
break;
}
Expand Down
15 changes: 13 additions & 2 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1958,7 +1958,7 @@ Objects/mimalloc/page.o: $(srcdir)/Objects/mimalloc/page-queue.c
regen-cases: \
regen-opcode-ids regen-opcode-targets regen-uop-ids regen-opcode-metadata-py \
regen-generated-cases regen-executor-cases regen-optimizer-cases \
regen-opcode-metadata regen-uop-metadata
regen-partial-evaluator-cases regen-opcode-metadata regen-uop-metadata

.PHONY: regen-opcode-ids
regen-opcode-ids:
Expand Down Expand Up @@ -2004,6 +2004,16 @@ regen-optimizer-cases:
$(srcdir)/Python/bytecodes.c
$(UPDATE_FILE) $(srcdir)/Python/optimizer_cases.c.h $(srcdir)/Python/optimizer_cases.c.h.new

.PHONY: regen-partial-evaluator-cases
regen-partial-evaluator-cases:
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/partial_evaluator_generator.py \
-o $(srcdir)/Python/partial_evaluator_cases.c.h.new \
$(srcdir)/Python/optimizer_bytecodes.c \
$(srcdir)/Python/partial_evaluator_bytecodes.c \
$(srcdir)/Python/bytecodes.c
$(UPDATE_FILE) $(srcdir)/Python/partial_evaluator_cases.c.h $(srcdir)/Python/partial_evaluator_cases.c.h.new


Fidget-Spinner marked this conversation as resolved.
Show resolved Hide resolved
.PHONY: regen-opcode-metadata
regen-opcode-metadata:
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/opcode_metadata_generator.py \
Expand Down Expand Up @@ -2041,7 +2051,8 @@ Python/optimizer.o: \
Python/optimizer_analysis.o: \
$(srcdir)/Include/internal/pycore_opcode_metadata.h \
$(srcdir)/Include/internal/pycore_optimizer.h \
$(srcdir)/Python/optimizer_cases.c.h
$(srcdir)/Python/optimizer_cases.c.h \
$(srcdir)/Python/partial_evaluator_cases.c.h

Python/frozen.o: $(FROZEN_FILES_OUT)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Set up a tier 2 partial evaluation pass. Patch by Ken Jin.
Loading
Loading