8000 gh-107557: Setup abstract interpretation by Fidget-Spinner · Pull Request #107847 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-107557: Setup abstract interpretation #107847

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

Merged
merged 54 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
d20fbb8
gh-107557: Tier 2 abstract interpreter barebones
Fidget-Spinner Aug 2, 2023
2aeea51
📜🤖 Added by blurb_it.
blurb-it[bot] Aug 2, 2023
1a728ab
Copy Guido's input and output code, and fix build
Fidget-Spinner Aug 2, 2023
17fccbc
fix separator
Fidget-Spinner Aug 2, 2023
a1da69d
credit Jules
Fidget-Spinner Aug 2, 2023
b458e17
add jules to co-authors
Fidget-Spinner Aug 2, 2023
f81f888
add pycore_optimizer.h to headers in makefile
Fidget-Spinner Aug 2, 2023
0020320
fix: remove whitespace
Fidget-Spinner Aug 2, 2023
1f93072
fix make smelly
Fidget-Spinner Aug 2, 2023
dac63e3
fix: build
Fidget-Spinner Aug 2, 2023
e62e015
fix wrong symbol
Fidget-Spinner Aug 2, 2023
a7f654c
ignore static globals check for abstract interpreter
Fidget-Spinner Aug 2, 2023
f4040b8
Merge remote-tracking branch 'upstream/main' into abstract_interpreter
Fidget-Spinner Aug 4, 2023
ec58145
merge Guido's changes
Fidget-Spinner Aug 4, 2023
4292767
remove unused stuff
Fidget-Spinner Aug 4, 2023
fdcca90
Turn on the abstract interpreter
Fidget-Spinner Aug 4, 2023
5110fb9
Merge remote-tracking branch 'upstream/main' into abstract_interpreter
Fidget-Spinner Aug 5, 2023
9f443a2
Merge remote-tracking branch 'origin/abstract_interpreter' into parti…
Fidget-Spinner Aug 5, 2023
7632ed1
(leaky) data structures for constant propagation
Fidget-Spinner Aug 5, 2023
0d0c4c4
(with cycles) try to fix the type prop
Fidget-Spinner Aug 6, 2023
4c8953e
fix: cycles
Fidget-Spinner Aug 6, 2023
3bd36fa
cleanup
Fidget-Spinner Aug 6, 2023
229097f
Fix+Refactor: Handling of root nodes in special-cased type prop (#40)
JuliaPoo Aug 7, 2023
ca0fab7
partially partially evaluate
Fidget-Spinner Aug 8, 2023
68c684f
rename vars
Fidget-Spinner Aug 8, 2023
46c5777
fixx off by one
Fidget-Spinner Aug 8, 2023
b839ee4
partial eval working for real this time
Fidget-Spinner Aug 9, 2023
6ecf3d2
Fix: Inconsistent `AbstractInterpContext` used in `PARTITIONNODE_OVER…
JuliaPoo Aug 9, 2023
b6eeb25
fix test, refactor, bugfix
Fidget-Spinner Aug 9, 2023
d5cceb9
re-compute jump offsets and targets
Fidget-Spinner Aug 10, 2023
8c0d65f
Fix+Refactor: Extra EXIT_TRACE emitted (#42)
JuliaPoo Aug 10, 2023
95db909
fix: overallocate buffer and virtual/real stack offset calculation
Fidget-Spinner Aug 10, 2023
1e05ef8
more bugfix
Fidget-Spinner Aug 10, 2023
d7d8b52
Merge remote-tracking branch 'upstream/main' into partition_algo
Fidget-Spinner Aug 10, 2023
4d7abc7
Perf+Cleanup: Removed temporary allocation in `remove_duplicate_save_…
JuliaPoo Aug 11, 2023
3d76f9a
clean up code
Fidget-Spinner Aug 11, 2023
e81def2
Merge branch 'partition_algo' of https://github.com/Fidget-Spinner/cp…
Fidget-Spinner Aug 11, 2023
9a5a3f7
make static
Fidget-Spinner Aug 11, 2023
df490d0
make types static
Fidget-Spinner Aug 11, 2023
1e4fc94
make const and ignore in c analyzer
Fidget-Spinner Aug 11, 2023
6de77a7
fix c-analyzer ignored list
Fidget-Spinner Aug 11, 2023
a11fc80
more cleanup
Fidget-Spinner Aug 13, 2023
c61015b
Merge remote-tracking branch 'upstream/main' into partition_algo
Fidget-Spinner Aug 13, 2023
56c62eb
regen files
Fidget-Spinner Aug 13, 2023
3c08ebe
address review
Fidget-Spinner Aug 14, 2023
d5f16be
regen
Fidget-Spinner Aug 14, 2023
1e61c49
and env var to block tests
Fidget-Spinner Aug 14, 2023
6c24b49
regen again
Fidget-Spinner Aug 14, 2023
2be404d
fix generated files
Fidget-Spinner Aug 14, 2023
29e255d
Address review
Fidget-Spinner Aug 15, 2023
3c44117
fix up INSERT
Fidget-Spinner Aug 15, 2023
b758b47
remove experimental parts
Fidget-Spinner Aug 15, 2023
80c7f18
revert more changes
Fidget-Spinner Aug 15, 2023
6a2b204
use memmove
Fidget-Spinner Aug 15, 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
Prev Previous commit
Next Next commit
fix test, refactor, bugfix
  • Loading branch information
Fidget-Spinner committed Aug 9, 2023
commit b6eeb25d11717c46c87516b58a10538a3af4bc95
4 changes: 2 additions & 2 deletions Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2729,8 +2729,8 @@ def testfunc(loops):
ex = get_first_executor(testfunc)
self.assertIsNotNone(ex)
self.assertEqual(res, 9)
binop_count = [opname == "_BINARY_OP_ADD_INT" for opname, _, _ in ex]
self.assertEqual(binop_count, 1)
binop_count = [opname for opname, _, _ in ex if opname == "_BINARY_OP_ADD_INT"]
self.assertEqual(len(binop_count), 1)

if __name__ == "__main__":
unittest.main()
220 changes: 67 additions & 153 deletions Python/optimizer_analysis.c
9E88
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

#define PARTITION_DEBUG 1

#define STATIC 0
#define DYNAMIC 1

// TYPENODE is a tagged pointer that uses the last 2 LSB as the tag
#define _Py_PARTITIONNODE_t uintptr_t

Expand Down Expand Up @@ -417,6 +420,57 @@ partitionnode_overwrite(_Py_UOpsAbstractInterpContext *ctx,

#if PARTITION_DEBUG

void
print_ctx_node(_Py_UOpsAbstractInterpContext *ctx, int i, bool is_printing_stack, int nstack_use, int nstack)
{
bool is_local = false;
bool is_stack = false;

int locals_offset = -1;
int stack_offset = -1;
int parent_idx = -1;

_Py_PARTITIONNODE_t *node = is_printing_stack ? &ctx->stack[i] : &ctx->locals[i];
_Py_PARTITIONNODE_t tag = partitionnode_get_tag(*node);

_Py_PARTITIONNODE_t *root = partitionnode_get_rootptr(node);

if (is_printing_stack) {
fprintf(stderr, "%s", i == nstack_use - 1 ? "." : " ");
}

if (tag == TYPE_REF) {
_Py_PARTITIONNODE_t *parent = (_Py_PARTITIONNODE_t *)(partitionnode_clear_tag(*node));
int local_index = (int)(parent - ctx->locals);
int stack_index = (int)(parent - ctx->stack);
is_local = local_index >= 0 && local_index < ctx->locals_len;
is_stack = stack_index >= 0 && stack_index < nstack;
parent_idx = is_local
? local_index
: is_stack
? stack_index
: -1;
}


_Py_PartitionRootNode *ptr = (_Py_PartitionRootNode *)partitionnode_clear_tag(*root);
fprintf(stderr, "%s:",
ptr == NULL ? "?" : (ptr->static_or_dynamic == STATIC ? "static" : "dynamic"));
if (ptr != NULL && ptr->static_or_dynamic == STATIC) {
PyObject_Print(ptr->const_val, stderr, 0);
}

if (tag == TYPE_REF) {
const char *wher = is_local
? "locals"
: is_stack
? "stack"
: "const";
fprintf(stderr, "->%s[%d]",
wher, parent_idx);
}
}

/**
* @brief Print the entries in the abstract interpreter context (along with locals).
*/
Expand All @@ -430,92 +484,16 @@ print_ctx(_Py_UOpsAbstractInterpContext *ctx)
int nstack = ctx->stack_len;
int nlocals = ctx->locals_len;

bool is_local = false;
bool is_stack = false;

int locals_offset = -1;
int stack_offset = -1;
int parent_idx = -1;

fprintf(stderr, " Stack: %p: [", ctx->stack);
for (int i = 0; i < nstack; i++) {
_Py_PARTITIONNODE_t *node = &ctx->stack[i];
_Py_PARTITIONNODE_t tag = partitionnode_get_tag(*node);

_Py_PARTITIONNODE_t *root = partitionnode_get_rootptr(node);

fprintf(stderr, "%s", i == nstack_use ? "." : " ");

if (tag == TYPE_REF) {
_Py_PARTITIONNODE_t *parent = (_Py_PARTITIONNODE_t *)(partitionnode_clear_tag(*node));
int local_index = (int)(parent - ctx->locals);
int stack_index = (int)(parent - ctx->stack);
is_local = local_index >= 0 && local_index < ctx->locals_len;
is_stack = stack_index >= 0 && stack_index < nstack;
parent_idx = is_local
? local_index
: is_stack
? stack_index
: -1;
}


_Py_PartitionRootNode *ptr = (_Py_PartitionRootNode *)partitionnode_clear_tag(*root);
fprintf(stderr, "%s:",
ptr == NULL ? "?" : (ptr->static_or_dynamic == 0 ? "static" : "dynamic"));
if (ptr != NULL && ptr->static_or_dynamic == 0) {
PyObject_Print(ptr->const_val, stderr, 0);
}

if (tag == TYPE_REF) {
const char *wher = is_local
? "locals"
: is_stack
? "stack"
: "const";
fprintf(stderr, "->%s[%d]",
wher, parent_idx);
}
print_ctx_node(ctx, i, true, nstack_use, nstack);
fprintf(stderr, " | ");
}
fprintf(stderr, "]\n& 8000 quot;);

fprintf(stderr, " Locals %p: [", locals);
for (int i = 0; i < nlocals; i++) {
_Py_PARTITIONNODE_t *node = &ctx->locals[i];
_Py_PARTITIONNODE_t tag = partitionnode_get_tag(*node);

_Py_PARTITIONNODE_t *root = partitionnode_get_rootptr(node);

if (tag == TYPE_REF) {
_Py_PARTITIONNODE_t *parent = (_Py_PARTITIONNODE_t *)(partitionnode_clear_tag(*node));
int local_index = (int)(parent - ctx->locals);
int stack_index = (int)(parent - ctx->stack);
is_local = local_index >= 0 && local_index < ctx->locals_len;
is_stack = stack_index >= 0 && stack_index < nstack;
parent_idx = is_local
? local_index
: is_stack
? stack_index
: -1;
}

_Py_PartitionRootNode *ptr = (_Py_PartitionRootNode *)partitionnode_clear_tag(*root);
fprintf(stderr, "%s:",
ptr == NULL ? "?" : (ptr->static_or_dynamic == 0 ? "static" : "dynamic"));
if (ptr != NULL && ptr->static_or_dynamic == 0) {
PyObject_Print(ptr->const_val, stderr, 0);
}

if (tag == TYPE_REF) {
const char *wher = is_local
? "locals"
: is_stack
? "stack"
: "const";
fprintf(stderr, "->%s[%d]",
wher, parent_idx);
}
print_ctx_node(ctx, i, false, nstack_use, nstack);
fprintf(stderr, " | ");
}
fprintf(stderr, "]\n");
Expand All @@ -530,7 +508,7 @@ partitionnode_is_static(_Py_PARTITIONNODE_t *node)
if (root_obj == _Py_NULL) {
return false;
}
return root_obj->static_or_dynamic == 0;
return root_obj->static_or_dynamic == STATIC;
}

// MUST BE GUARDED BY partitionnode_is_static BEFORE CALLING THIS
Expand Down Expand Up @@ -754,6 +732,16 @@ _Py_uop_analyze_and_optimize(
temp_writebuffer[buffer_trace_len] = insert;
buffer_trace_len++;
}
#if PARTITION_DEBUG
fprintf(stderr, "Emitting SAVE_IP\n");
#endif
// Use the next SAVE_IP
int temp = i;
for (; trace[temp].opcode != SAVE_IP && temp < trace_len; temp++) {
}
assert(trace[temp].opcode == SAVE_IP);
temp_writebuffer[buffer_trace_len] = trace[temp];
buffer_trace_len++;
num_dynamic_operands++;
}

Expand Down Expand Up @@ -890,80 +878,6 @@ _Py_uop_analyze_and_optimize(
for (int y = stack_outputs; y > 0; y--) {
stack_virtual_or_real[STACK_LEVEL() - y] = !should_emit;
}
// if (should_emit) {
//
// // Emit instruction
// temp_writebuffer[buffer_trace_len] = trace[i];
// buffer_trace_len++;
//
// // Update the real abstract interpreter
// stack_pointer = ctx->real_stack_pointer;
// locals = ctx->real_locals;
// stack = ctx->real_stack;
//
// /*
// * The following are special cased:
// * @TODO: shift these to the DSL
// */
// switch (opcode) {
//#include "abstract_interp_cases.c.h"
// // @TODO convert these to autogenerated using DSL
// case LOAD_FAST:
// case LOAD_FAST_CHECK:
// STACK_GROW(1);
// PARTITIONNODE_OVERWRITE(GETLOCAL(oparg), PEEK(1), false);
// break;
// case LOAD_FAST_AND_CLEAR: {
// STACK_GROW(1);
// PARTITIONNODE_OVERWRITE(GETLOCAL(oparg), PEEK(1), false);
// PARTITIONNODE_OVERWRITE(&PARTITIONNODE_NULLROOT, GETLOCAL(oparg), false);
// break;
// }
// case LOAD_CONST: {
// _Py_PARTITIONNODE_t value = MAKE_STATIC_ROOT(GETITEM(co->co_consts, oparg));
// STACK_GROW(1);
// PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)value, PEEK(1), false);
// break;
// }
// case STORE_FAST:
// case STORE_FAST_MAYBE_NULL: {
// _Py_PARTITIONNODE_t *value = PEEK(1);
// PARTITIONNODE_OVERWRITE(value, GETLOCAL(oparg), false);
// STACK_SHRINK(1);
// break;
// }
// case COPY: {
// _Py_PARTITIONNODE_t *bottom = PEEK(1 + (oparg - 1));
// STACK_GROW(1);
// PARTITIONNODE_SET(bottom, PEEK(1), false);
// break;
// }
//
// case _BINARY_OP_MULTIPLY_INT: {
// STACK_SHRINK(1);
// PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
// break;
//
// }
//
// case _BINARY_OP_ADD_INT: {
// STACK_SHRINK(1);
// PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
// break;
// }
//
// case _BINARY_OP_SUBTRACT_INT: {
// STACK_SHRINK(1);
// PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
// break;
// }
// default:
// fprintf(stderr, "Unknown opcode in abstract interpreter\n");
// Py_UNREACHABLE();
// }
//
// ctx->real_stack_pointer = stack_pointer;
// }
}
assert(STACK_SIZE() >= 0);
assert(buffer_trace_len <= trace_len);
Expand Down
0